<?php
/**
 * CDbSession class file.
 * Session存数据库.
 * 存数据库前，需要建session表，表名默认为session，可以自定义
 * 自定义表名时，需要将表名做为参数赋给构造方法
 * 如果修改表的字段，需要修改本类代码
 * CREATE TABLE session (
 *     session_id      char(32)     NOT NULL COMMENT 'SESSION_ID',
 * 	   dt_last_access  datetime     NOT NULL COMMENT '最后一次访问SESSION的时间',
 *     data            text         NOT NULL COMMENT 'SESSION的内容',
 *     url_last_access varchar(255) NOT NULL COMMENT '最后一次访问SESSION的页面',
 *     ip_last_access  char(16)     NOT NULL COMMENT '最后一次访问SESSION的IP地址',
 *     dt_start        datetime     NOT NULL COMMENT 'session_start的时间'
 * ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 * 
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CImage.php 1 2011-06-29 18:54:00Z huan.song $
 * @package system.helpers
 * @since 2.0
 */
class CDbSession
{
	protected $_db = null;
	protected $_table = '';
	
	public function __construct($table = 'session')
	{
		$this->_table = $table;
	}
	
	public function open($path, $name)
	{
		try 
		{
			$dbDriver = new CDbDriver();
			$dbDriver->active = true;
			$this->_db = new CDbStatement($dbDriver);
		}
		catch (CDbException $e)
		{
			return false;
		}
		return true;
	}
	
	public function close()
	{
		$this->_db = null;
		return true;
	}
	
	public function read($session_id)
	{
		$sql = 'SELECT data FROM ' . $this->_table . ' WHERE session_id = ?';
		return $this->_db->fetchColumnOneBySql($sql, $session_id);
	}
	
	public function write($session_id, $data)
	{
		$now = date('Y-m-d H:i:s');
		$request = CRequest::getInstance();
		
		$sql = 'SELECT COUNT(session_id) FROM ' . $this->_table . ' WHERE session_id = ?';
		if ($this->_db->fetchColumnOneBySql($sql, $session_id) > 0)
		{
			$sql = 'UPDATE ' . $this->_table . ' SET dt_last_access = ?, data = ?, url_last_access = ?, ip_last_access = ? WHERE session_id = ?';
			$param = array('dt_last_access'  => $now, 'data' => $data, 'url_last_access' => $request->url, 'ip_last_access'  => $request->clientIp, 'session_id' => $session_id);
		}
		else
		{
			$sql = 'INSERT INTO ' . $this->_table . ' (session_id, dt_last_access, data, url_last_access, ip_last_access, dt_start, user_id) VALUES (?, ?, ?, ?, ?, ?, ?)';
			$param = array('session_id' => $session_id, 'dt_last_access'  => $now, 'data' => $data, 'url_last_access' => $request->url, 
				'ip_last_access'  => $request->clientIp, 'dt_start' => $now, 'user_id' => 0);
		}
		return $this->_db->queryBySql($sql, $param);
	}
	
	public function destroy($session_id)
	{
		$sql = 'DELETE FROM ' . $this->_table . ' WHERE session_id = ?';
		$this->_db->queryBySql($sql, $session_id);
		return $this->_db->rowCount > 0;
	}
	
	public function gc($ttl)
	{
		$end = date('Y-m-d H:i:s', mktime() - $ttl);
		$sql = 'DELETE FROM ' . $this->_table . ' WHERE dt_last_access < ?';
		$this->_db->queryBySql($sql, $end);
		return $this->_db->rowCount > 0;
	}
	
	public function __destruct()
	{
		session_write_close();
	}
}

$session = new CDbSession(CConfig::get('config', 'session_save_table'));
session_set_save_handler(
	array($session, 'open'),
	array($session, 'close'),
	array($session, 'read'),
	array($session, 'write'),
	array($session, 'destroy'),
	array($session, 'gc')
);
